/**
 * ParamServiceImpl.java
 * com.sitech.dmcs.core.impl
 * Function： TODO 
 *
 *   ver  author   date    
 * ──────────────────────────────────
 *   	 geutopia  Jan 14, 2011        
 *
 * Copyright (c) 2011, TNT All Rights Reserved.
 */

package com.sitech.timing.param.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;

import com.sitech.context.SpringContext;
import com.sitech.timing.QueryService;
import com.sitech.timing.TimingConst;
import com.sitech.timing.dao.ParamDao;
import com.sitech.timing.domain.ParamDetail;
import com.sitech.timing.domain.ParamInfo;
import com.sitech.timing.domain.ParamInstance;
import com.sitech.timing.domain.ParamTaskTypeRelation;
import com.sitech.timing.domain.ParamType;
import com.sitech.timing.domain.TaskInfo;
import com.sitech.timing.domain.TaskInstance;
import com.sitech.timing.domain.TaskResult;
import com.sitech.timing.domain.TaskType;
import com.sitech.timing.param.ParamConvert;
import com.sitech.timing.param.ParamObjectFactoy;
import com.sitech.timing.param.ParamService;



/**
 * ClassName:ParamServiceImpl Function: TODO ADD FUNCTION Reason: TODO ADD
 * REASON
 * 
 * @author geutopia
 * @version
 * @since Ver 1.1
 * @Date 2011 Jan 14, 2011 5:10:46 PM
 * 
 * @see
 */

public class ParamServiceImpl implements ParamService
{

	private ParamObjectFactoy defaultParamObjectFactoy;
	private ParamConvert defaultParamConvert;
	private ParamDao paramDao;
	private QueryService queryService;

	/**
	 * (non-Javadoc)
	 * 
	 * @see com.sitech.dmcs.core.param.ParamService#produceParamMap(com.sitech.dmcs.core.domain.TaskInstance)
	 */
	public Map<String, Object> produceParamMap(TaskInstance taskInstance)
	{
		TaskInfo taskInfo = queryService.getTaskInfo(taskInstance.getGroupTaskId(), taskInstance.getTaskId());
		TaskType taskType = taskInfo.getTaskType();

		List<ParamTaskTypeRelation> paramTaskTypeRelationList = taskType.getParamTaskTypeRelationList();
		List<ParamInfo> paramInfoList = taskInfo.getParamInfoList();
		return produceParamMap(taskInstance, paramTaskTypeRelationList, paramInfoList);
	}

	public Object produceParamObject(ParamType paramType)
	{
		ParamObjectFactoy paramObjectFactoy = null;

		if (paramType.getObjectFactory() != null && !"".equals(paramType.getObjectFactory()))
		{
			paramObjectFactoy = getParamObjectFactoy(paramType.getObjectFactory());
		}

		if (paramObjectFactoy == null)
		{
			paramObjectFactoy = defaultParamObjectFactoy;
		}

		Object paramObject = paramObjectFactoy.createParamObject(paramType.getParamClass());
		return paramObject;
	}

	private Map<String, Object> produceParamMap(TaskInstance taskInstance,
			List<ParamTaskTypeRelation> paramTaskTypeRelationList, List<ParamInfo> paramInfoList)
	{

		if (paramTaskTypeRelationList != null && paramTaskTypeRelationList.size() > 0)
		{
			List<ParamInstance> paramInstanceList = new ArrayList<ParamInstance>();

			Map<String, Object> paramMap = new HashMap<String, Object>();

			for (ParamTaskTypeRelation paramTaskTypeRelation : paramTaskTypeRelationList)
			{
				if (paramTaskTypeRelation != null
						&& paramTaskTypeRelation.getRelationType() != null
						&& (TimingConst.PARAM_TASKTYPE_RELATION_IN.equals(paramTaskTypeRelation.getRelationType().trim()) || paramTaskTypeRelation
								.getRelationType().trim().equals("")))
				{
					List<ParamInfo> paramVauleList = new ArrayList<ParamInfo>();

					for (ParamInfo paramInfo : paramInfoList)
					{
						if (paramInfo.getRelationId() == null || "".equals(paramInfo.getRelationId()))
						{
							if (paramInfo.getParamTypeId().equals(paramTaskTypeRelation.getParamTypeId()))
							{
								paramVauleList.add(paramInfo);
							}
						}
						else if (paramInfo.getRelationId().equals(paramTaskTypeRelation.getId()))
						{
							paramVauleList.add(paramInfo);
						}
					}
					Object paramObject = produceParamObject(taskInstance, paramTaskTypeRelation.getParamType(),
							paramVauleList, paramInstanceList);

					if (paramObject instanceof Map)
					{
						Map paramObjectMap = (Map) paramObject;
						paramMap.putAll(paramObjectMap);
					}
					else
					{
						if (paramTaskTypeRelation.getParamName() != null)
						{
							paramMap.put(paramTaskTypeRelation.getParamName(), paramObject);
						}
						else
						{
							paramMap.put(paramTaskTypeRelation.getParamType().getParamTypeName(), paramObject);
						}

					}
				}

			}
			paramDao.deleteTaskParamInstance(taskInstance.getTaskInstanceId());
			paramDao.insertParamInstanceBatch(paramInstanceList);
			return paramMap;
		}
		else
		{
			return null;
		}
	}

	/**
	 * 
	 * produceParamObject:(这里用一句话描述这个方法的作用) TODO(这里描述这个方法适用条件 – 可选)
	 * TODO(这里描述这个方法的执行流程 – 可选) TODO(这里描述这个方法的使用方法 – 可选) TODO(这里描述这个方法的注意事项 –
	 * 可选)
	 * 
	 * @param taskInstance
	 * @param paramType
	 * @param paramVauleList
	 * @return
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws ClassNotFoundException
	 * @throws
	 * @since Ver 1.1
	 * @deprecated 还没有做好 1、没有增加创建工厂的选择， 2、没有添加从原来的结果中获取输入的
	 */
	private Object produceParamObject(TaskInstance taskInstance, ParamType paramType, List<ParamInfo> paramVauleList,
			List<ParamInstance> paramInstanceList)
	{
		List<ParamDetail> paramDetaillist = paramType.getParamDetailList();

		Map<String, ParamDetail> paramDetailMap = new HashMap<String, ParamDetail>();
		Map<String, Object> paramValueMap = new HashMap<String, Object>();

		if (paramDetaillist != null)
		{
			for (ParamDetail paramDetail : paramDetaillist)
			{
				paramDetailMap.put(paramDetail.getParamName(), paramDetail);
			}
		}

		for (ParamInfo paramInfo : paramVauleList)
		{

			Object object = null;

			if (paramInfo.getParamValueType() != null && !"".equals(paramInfo.getParamValue()))
			{
				ParamConvert paramConvert = getParamConvert(paramInfo.getParamValueType().trim());
				object = paramConvert.Convert(paramInfo, paramType, taskInstance);

				try
				{
					if (object != null)
					{
						Map<String, Object> valueMap = null;
						if(object instanceof Map)
						{
							valueMap = (Map<String, Object>) object;
						}
						else
						{
							valueMap = BeanUtils.describe(object);
						}
						paramValueMap.putAll(valueMap);
						for (Map.Entry<String, Object> entry : valueMap.entrySet())
						{
							if (entry.getKey() != null && entry.getValue() != null)
							{
								ParamInstance paramInstance = createParamInstance(paramInfo.getParamInfoId(), entry
										.getKey(), paramInfo.getParamTypeId(), entry.getValue().toString(),
										taskInstance.getTaskId(), taskInstance.getTaskInstanceId());
								paramInstanceList.add(paramInstance);
							}
						}
					}
				}
				catch (Exception e)
				{

				}

				if (paramVauleList.size() == 1)
				{
					return object;
				}
			}
			else
			{
				try
				{
					String paramValue = paramInfo.getParamValue();
					String paramName = paramInfo.getParamName();

					ParamDetail paramDetail = paramDetailMap.get(paramName);
					if (paramDetail != null)
					{
						object = ConvertUtils.convert(paramValue, Class.forName(paramDetail.getJavaType()));
						paramValueMap.put(paramName, object);

					}
					else
					{
						object = paramValue;
						paramValueMap.put(paramName, paramValue);
					}
					if (object != null)
					{
						ParamInstance paramInstance = new ParamInstance();
						paramInstance.setParamInfoId(paramInfo.getParamInfoId());
						paramInstance.setParamName(paramInfo.getParamName());
						paramInstance.setParamTypeId(paramInfo.getParamTypeId());
						paramInstance.setParamvalue(object.toString());
						paramInstance.setTaskId(taskInstance.getTaskId());
						paramInstance.setTaskInstanceId(taskInstance.getTaskInstanceId());
						paramInstanceList.add(paramInstance);
					}
				}
				catch (ClassNotFoundException e)
				{
					e.printStackTrace();
				}
			}
		}

		Object paramObject = produceParamObject(paramType);

		try
		{
			BeanUtils.populate(paramObject, paramValueMap);
		}
		catch (IllegalAccessException e)
		{
			e.printStackTrace();
		}
		catch (InvocationTargetException e)
		{
			e.printStackTrace();
		}

		return paramObject;
	}

	private ParamObjectFactoy getParamObjectFactoy(String paramObjectFactoyName)
	{
		try
		{
			return (ParamObjectFactoy) SpringContext.getBean(paramObjectFactoyName);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}

	private ParamConvert getParamConvert(String paramConvertName)
	{
		try
		{
			ParamConvert paramConvert = (ParamConvert) SpringContext.getBean(paramConvertName);
			return paramConvert;
		}
		catch (Exception e)
		{
			try
			{
				return (ParamConvert) SpringContext.getBean(paramConvertName + "ParamConvert");
			}
			catch (Exception exception)
			{
				e.printStackTrace();
				exception.printStackTrace();
				return null;
			}
		}
	}

	public ParamObjectFactoy getDefaultParamObjectFactoy()
	{
		return defaultParamObjectFactoy;
	}

	public void setDefaultParamObjectFactoy(ParamObjectFactoy defaultParamObjectFactoy)
	{
		this.defaultParamObjectFactoy = defaultParamObjectFactoy;
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see com.sitech.dmcs.core.param.ParamService#produceParamInstanceMap(com.sitech.dmcs.core.domain.TaskInstance)
	 */
	public Map<String, Object> produceParamInstanceMap(TaskInstance taskInstance)
	{
		Map<String, Object> map = new HashMap<String, Object>();

		ParamInstance queryParamInstance = new ParamInstance();
		queryParamInstance.setTaskInstanceId(taskInstance.getTaskInstanceId());
		List<ParamInstance> paramInstanceList = paramDao.getTaskParamInstance(queryParamInstance);

		TaskInfo taskInfo = queryService.getTaskInfo(taskInstance.getGroupTaskId(), taskInstance.getTaskId());
		List<ParamTaskTypeRelation> relationList = taskInfo.getTaskType().getParamTaskTypeRelationList();

		for (ParamTaskTypeRelation paramTaskTypeRelation : relationList)
		{
			ParamType paramType = paramTaskTypeRelation.getParamType();

			Object object = produceParamObject(paramType);
			Map<String, Object> paramValueMap = new HashMap<String, Object>();

			for (ParamInstance paramInstance : paramInstanceList)
			{
				if (paramInstance.getParamTypeId().equals(paramType.getParamTypeId()))
				{
					paramValueMap.put(paramInstance.getParamName(), paramInstance.getParamvalue());
				}
			}

			try
			{
				BeanUtils.populate(object, paramValueMap);
			}
			catch (IllegalAccessException e)
			{
				e.printStackTrace();
			}
			catch (InvocationTargetException e)
			{
				e.printStackTrace();
			}

			if (object instanceof Map)
			{
				Map paramObjectMap = (Map) object;
				map.putAll(paramObjectMap);
			}
			else
			{
				if (paramTaskTypeRelation.getParamName() != null && !"".equals(paramTaskTypeRelation.getParamName()))
				{
					map.put(paramTaskTypeRelation.getParamName(), object);
				}
				else
				{
					map.put(paramType.getParamTypeName(), object);

				}
			}

		}

		return map;
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see com.sitech.dmcs.core.param.ParamService#insertResult(com.sitech.dmcs.core.domain.TaskInstance,
	 *      com.sitech.dmcs.core.domain.TaskResult)
	 */
	public void insertResult(TaskInstance taskInstance, TaskResult taskResult)
	{
		List<ParamInstance> paramInstanceList = new ArrayList<ParamInstance>();

		TaskInfo taskInfo = queryService.getTaskInfo(taskInstance.getGroupTaskId(), taskInstance.getTaskId());
		TaskType taskType = taskInfo.getTaskType();
		List<ParamInfo> paramInfoList = taskInfo.getParamInfoList();

		List<ParamTaskTypeRelation> paramTaskTypeRelationList = taskType.getParamTaskTypeRelationList();
		if (taskResult != null && taskResult.getResultMap() != null && paramTaskTypeRelationList != null && paramTaskTypeRelationList.size() > 0)
		{
			Map<String, Object> resultMap = taskResult.getResultMap();
			for (ParamTaskTypeRelation paramTaskTypeRelation : paramTaskTypeRelationList)
			{

				ParamType paramType = paramTaskTypeRelation.getParamType();
				if (paramTaskTypeRelation != null && paramTaskTypeRelation.getRelationType() != null
						&& TimingConst.PARAM_TASKTYPE_RELATION_OUT.equals(paramTaskTypeRelation.getRelationType()))
				{
					Object object = produceParamObject(paramType);

					for (ParamInfo paramInfo : paramInfoList)
					{
						if (((paramInfo.getRelationId() == null || "".equals(paramInfo.getRelationId())) && paramInfo
								.getParamTypeId().equals(paramTaskTypeRelation.getParamTypeId()))
								|| paramTaskTypeRelation.getId().equals(paramInfo.getRelationId()))
						{
							Map<String, Object> valueMap = null;

							if (object instanceof Map)
							{
								valueMap = resultMap;
							}
							else
							{
								try
								{
									Object value = valueMap.get(paramInfo.getParamName());
									valueMap = BeanUtils.describe(value);

								}
								catch (Exception exception)
								{
									exception.printStackTrace();
								}

							}
							for (Map.Entry<String, Object> entry : valueMap.entrySet())
							{
								if (entry.getKey() != null && entry.getValue() != null)
								{
									ParamInstance paramInstance = createParamInstance(paramInfo.getParamInfoId(), entry
											.getKey(), paramInfo.getParamTypeId(), entry.getValue().toString(),
											taskInstance.getTaskId(), taskInstance.getTaskInstanceId());
									paramInstanceList.add(paramInstance);
								}
							}
						}

					}
				}
			}
			paramDao.insertParamInstanceBatch(paramInstanceList);
		}
	}

	private ParamInstance createParamInstance(String paramInfoId, String paramName, String paramTypeId,
			String paramvalue, String taskId, String taskInstanceId)
	{
		ParamInstance paramInstance = new ParamInstance();
		paramInstance.setParamInfoId(paramInfoId);
		paramInstance.setParamName(paramName);
		paramInstance.setParamTypeId(paramTypeId);
		paramInstance.setParamvalue(paramvalue);
		paramInstance.setTaskId(taskId);
		paramInstance.setTaskInstanceId(taskInstanceId);
		return paramInstance;
	}

	public ParamDao getParamDao()
	{
		return paramDao;
	}

	public void setParamDao(ParamDao paramDao)
	{
		this.paramDao = paramDao;
	}

	public QueryService getQueryService()
	{
		return queryService;
	}

	public void setQueryService(QueryService queryService)
	{
		this.queryService = queryService;
	}

}
